package org.bobo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.SecurityUtils;
import org.bobo.bean.CollectDO;
import org.bobo.bean.UserDO;
import org.bobo.bean.VideoSetClickRecordDO;
import org.bobo.bean.VideoSetDO;
import org.bobo.common.api.vo.Result;
import org.bobo.common.constant.enums.BaseEnums;
import org.bobo.common.constant.enums.ExceptionEnums;
import org.bobo.common.exception.BusinessException;
import org.bobo.common.util.oConvertUtils;
import org.bobo.dto.VideoSetDTO;
import org.bobo.mapper.VideoSetDOMapper;
import org.bobo.service.IChasingDramaDOService;
import org.bobo.service.IVideoSetClickRecordDOService;
import org.bobo.service.IVideoSetDOService;
import org.bobo.vo.VideoSetVO;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 视频合集管理
 * @Author: boBo
 * @Date: 2023-04-09
 * @Version: V1.0
 */
@Service
public class VideoSetDOServiceImpl extends ServiceImpl<VideoSetDOMapper, VideoSetDO> implements IVideoSetDOService {
    @Autowired
    private IChasingDramaDOService chasingDramaDOService;
    @Autowired
    private IVideoSetClickRecordDOService videoSetClickRecordDOService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 全查询 如果没传参数默认返回10条
     *
     * @param videoSetDTO 数据传输对象
     * @return 视频专辑列表
     */
    @Override
    public List<VideoSetVO> customList(VideoSetDTO videoSetDTO) {
        LambdaQueryWrapper<VideoSetDO> lambdaQueryWrapper = videoSetDTO.initQueryWrapper(videoSetDTO);
        return baseMapper.customList(lambdaQueryWrapper);
    }

    /**
     * 今日热门查询
     *
     * @param videoSetDTO
     * @return List<VideoSetVO>
     */
    @Override
    public List<VideoSetVO> videoSetHostList(VideoSetDTO videoSetDTO) {
        QueryWrapper<VideoSetDO> queryWrapper = new QueryWrapper<>();
        //根据专辑分类查询
        queryWrapper.eq(oConvertUtils.isNotEmpty(videoSetDTO.getCategoryName()), "vs.category_name", videoSetDTO.getCategoryName());
        //根据专辑名称模糊查询
        queryWrapper.like(oConvertUtils.isNotEmpty(videoSetDTO.getSetName()), "vs.set_name", videoSetDTO.getSetName());
        //是否精选
        queryWrapper.eq(oConvertUtils.isNotEmpty(videoSetDTO.getCarefullyChosen()), "vs.carefully_chosen", videoSetDTO.getCarefullyChosen());
        //排序
        queryWrapper.orderByDesc("dayClickCount");
        //动态limit
        queryWrapper.last(oConvertUtils.isNotEmpty(videoSetDTO.getLimit()), BaseEnums.LIMIT.getValue() + " " + videoSetDTO.getLimit());

        return baseMapper.videoSetHostList(queryWrapper);
    }

    /**
     * 本周热门查询
     *
     * @param videoSetDTO
     * @return List<VideoSetVO>
     */
    @Override
    public List<VideoSetVO> videoSetHostListByWeek(VideoSetDTO videoSetDTO) {
        QueryWrapper<VideoSetDO> queryWrapper = new QueryWrapper<>();
        //根据专辑分类查询
        queryWrapper.eq(oConvertUtils.isNotEmpty(videoSetDTO.getCategoryName()), "vs.category_name", videoSetDTO.getCategoryName());
        //根据专辑名称模糊查询
        queryWrapper.like(oConvertUtils.isNotEmpty(videoSetDTO.getSetName()), "vs.set_name", videoSetDTO.getSetName());
        //是否精选
        queryWrapper.eq(oConvertUtils.isNotEmpty(videoSetDTO.getCarefullyChosen()), "vs.carefully_chosen", videoSetDTO.getCarefullyChosen());
        //排序
        queryWrapper.orderByDesc("dayClickCount");
        //动态limit
        queryWrapper.last(oConvertUtils.isNotEmpty(videoSetDTO.getLimit()), BaseEnums.LIMIT.getValue() + " " + videoSetDTO.getLimit());

        return baseMapper.videoSetHostListByWeek(queryWrapper);
    }

    /**
     * 推荐 数据量较少，暂时按照时间倒序分页
     *
     * @param videoSetDTO 参数
     * @return List<VideoSetDO>
     */
    @Override
    public IPage<VideoSetVO> recommend(Page<VideoSetDO> page, VideoSetDTO videoSetDTO) {
        LambdaQueryWrapper<VideoSetDO> lambdaQueryWrapper = videoSetDTO.initQueryWrapper(videoSetDTO);
        return baseMapper.customPage(page, lambdaQueryWrapper);
    }

    /**
     * 通过id查询
     *
     * @param id 专辑id
     * @return VideoSetVO
     */
    @Override
    public VideoSetVO customGetById(String id) {
        VideoSetDO videoSetDO = baseMapper.selectById(id);

        if (videoSetDO == null) {
            throw new BusinessException(ExceptionEnums.VIDEO_SET_NOT_FIND);
        }
        VideoSetVO videoSetVO = new VideoSetVO();
        BeanUtil.copyProperties(videoSetDO, videoSetVO);

        return videoSetVO;
    }

    @Override
    public IPage<VideoSetVO> customPage(Page<VideoSetDO> page, VideoSetDTO videoSetDTO) {
        LambdaQueryWrapper<VideoSetDO> lambdaQueryWrapper = videoSetDTO.initQueryWrapper(videoSetDTO);
        return baseMapper.customPage(page, lambdaQueryWrapper);
    }

    @Override
    public IPage<VideoSetVO> recommendAuth(Page<VideoSetDO> page, VideoSetDTO videoSetDTO) {
        UserDO userDO = (UserDO) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<VideoSetDO> lambdaQueryWrapper = videoSetDTO.initQueryWrapper(videoSetDTO);
        IPage<VideoSetVO> videoSetVOIPage = baseMapper.customPage(page, lambdaQueryWrapper);

        videoSetVOIPage.getRecords().forEach(videoSetVO -> {
            if (chasingDramaDOService.getByUserIdCommentId(videoSetVO.getId(), userDO.getId()) != null) {
                videoSetVO.setChasingDrama(true);
            } else {
                videoSetVO.setChasingDrama(false);
            }
        });
        return videoSetVOIPage;
    }

    @Override
    public void addClick(Long videoSetId, String ipAddr) {
        UserDO user = (UserDO) SecurityUtils.getSubject().getPrincipal();
        //从这里开始加锁
        RLock rLock = redissonClient.getLock("addClick--" + videoSetId + "--" + ipAddr);
        try {
            if (rLock.tryLock(15, TimeUnit.SECONDS)) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String tempDate = simpleDateFormat.format(new Date());
                //如果这个ip今天给这个合集贡献过一个点击量了那就不操作
                VideoSetClickRecordDO one = videoSetClickRecordDOService.getOne(new LambdaQueryWrapper<VideoSetClickRecordDO>().eq(VideoSetClickRecordDO::getVideoSetId, videoSetId).eq(VideoSetClickRecordDO::getIpAddress, ipAddr)
                        .ge(VideoSetClickRecordDO::getCreateTime, tempDate).last("limit 1"));
                if (one == null) {
                    VideoSetClickRecordDO videoSetClickRecordDO=new VideoSetClickRecordDO();
                    videoSetClickRecordDO.setVideoSetId(videoSetId);
                    videoSetClickRecordDO.setIpAddress(ipAddr);
                    videoSetClickRecordDOService.save(videoSetClickRecordDO);
                }
            } else {
                throw new BusinessException(ExceptionEnums.TO_FAST);
            }

        } catch (Exception e) {
            throw new BusinessException(ExceptionEnums.TO_FAST);
        } finally {
            //释放锁
            rLock.unlock();
        }
    }

    /**
     * 设置为精选合集
     *
     * @param id
     * @return
     */
    @Override
    public void carefullyChosen(String id) {
        VideoSetDO videoSetDO = baseMapper.selectById(id);
        if (videoSetDO == null) {
            throw new BusinessException(ExceptionEnums.VIDEO_SET_NOT_FIND);
        }
        videoSetDO.setCarefullyChosen(Integer.valueOf(BaseEnums.IS_CAREFULLY_CHOSEN.getValue()));
        int i = baseMapper.updateById(videoSetDO);

        if (i < 1) {
            throw new BusinessException(ExceptionEnums.SYSTEM_ERROR);
        }
    }

    /**
     * 取消精选
     *
     * @param id
     * @return
     */
    @Override
    public void unCarefullyChosen(String id) {
        VideoSetDO videoSetDO = baseMapper.selectById(id);
        if (videoSetDO == null) {
            throw new BusinessException(ExceptionEnums.VIDEO_SET_NOT_FIND);
        }
        videoSetDO.setCarefullyChosen(Integer.valueOf(BaseEnums.UN_CAREFULLY_CHOSEN.getValue()));
        int i = baseMapper.updateById(videoSetDO);

        if (i < 1) {
            throw new BusinessException(ExceptionEnums.SYSTEM_ERROR);
        }
    }
}
